package com.xquant.pricing.calc.service.impl;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.xquant.pricing.calc.entity.CalcLog;
import com.xquant.pricing.calc.mapper.CalcEngineMapper;
import com.xquant.pricing.calc.service.CalcLogsService;
import com.xquant.pricing.sysconfig.service.ISystemConfigService;
import com.xquant.pricing.utils.CreateFileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Auther: B946
 * @Date: 18/03/2020 11:18
 * @Description:
 */
@Service
public class CalcLogsServiceImpl implements CalcLogsService {

    private static ExecutorService fixedPool = new ThreadPoolExecutor(10,
            100,
            10L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1000000),
            new ThreadFactoryBuilder().setNamePrefix("calclog-save-pool-").build());
    Logger logger = LoggerFactory.getLogger(CalcLogsService.class);

    @Autowired
    private CalcEngineMapper calcEngineMapper;

    @Autowired
    private ISystemConfigService systemConfigService;

    /**
     * 保存日志
     *
     * @param params
     */
    @Override
    public void saveCalcLog(Map<String, Object> params) {

        calcEngineMapper.saveCalcLog(params);
    }

    /**
     * 由于downReq的值太长，有7000，如果在mybatis中使用foreach会报错，
     * 故，只能在方法中循环插入
     *
     * @param params
     */
    @Override
    public void saveReqAndResp(Map<String, Object> params) {
        String writeLogType = systemConfigService.selectConfigByKey("writeLogType");
        if ("file".equals(writeLogType)) {
            writeLogFile(params);

        } else if ("db".equals(writeLogType)) {
            writeLogDB(params);
        }
    }

    private void writeLogDB(Map<String, Object> params) {
        fixedPool.execute(() -> {
            calcEngineMapper.saveCalcLog(params);

        });
    }


    private void writeLogFile(Map<String, Object> params) {
        List rows = new ArrayList();
        if (((List) params.get("downparams")).size() > 0) {
            for (Object param : ((List) params.get("downparams"))) {
                //((Map) param).put("id", params.get("id"));
                Object[] objects = ((Map<String, Object>) param).entrySet().stream().map(e -> new String(e.getKey() + ":" + e.getValue().toString() + ";")).collect(Collectors.toList()).toArray();
                rows.add(objects);
            }
        }

        Object[] collect = params.entrySet().stream().map(e -> new String(e.getKey() + ":" + e.getValue().toString() + ";")).collect(Collectors.toList()).toArray();
        rows.add(collect);
        CreateFileUtil.createTxtFile(rows, System.getProperty("user.dir") + File.separator + "calcLogFiles" + File.separator + LocalDate.now() + File.separator + "logs", LocalDate.now() + "calcLog");
    }

    @Override
    public List<CalcLog> queryCalcLogs(Map<String, Object> params) {
        List<CalcLog> list = calcEngineMapper.queryCalcLogs(params);
        return list;
    }

    @Override
    public List<CalcLog> queryCalcLogsByName(Map<String, Object> params) {
        List<CalcLog> list = calcEngineMapper.queryCalcLogsByName(params);
        return list;
    }

    @Override
    public void deleteCalcLogs(Map<String, Object> params) {
        calcEngineMapper.deleteCalcLogs(params);

    }

}
